package cn.nju.seg.atg.util;

import cn.nju.seg.atg.model.Coodinate;
import cn.nju.seg.atg.model.Interval;

/**
 * 一元线性拟合函数
 * @author ChengXin
 *
 */
public class CLF {
	
	/**
	 * 用于线性拟合的两个坐标c1(x1,y1),c2(x2,y2)
	 */
	private Coodinate c1;
	private Coodinate c2;
	
	/**
	 * 比较运算符
	 */
	private int comparisonOperator;
	
	/**
	 * 初始化函数
	 * @param c1
	 * @param c2
	 * @param comparisonOperator
	 */
	public CLF(Coodinate c1, Coodinate c2, int comparisonOperator)
	{
		this.c1 = c1;
		this.c2 = c2;
		this.comparisonOperator = comparisonOperator;
	}
	
	/**
	 * 计算有效取值区间
	 * @return 一个区间
	 */
	public Interval getEffectiveInterval()
	{
		Interval interval = new Interval();
		
		if (this.comparisonOperator == ConstantValue.SYMBOL_GREATER || this.comparisonOperator == ConstantValue.SYMBOL_GREATER_EQUAL)
		{
			interval = getGreaterInterval();
		}
		else if (this.comparisonOperator == ConstantValue.SYMBOL_LESS || this.comparisonOperator == ConstantValue.SYMBOL_LESS_EQUAL)
		{
			interval = getLessInteval();
		}
		else if (this.comparisonOperator == ConstantValue.SYMBOL_EQUAL)
		{
			interval = getEqualInterval();
		}
		else if (this.comparisonOperator == ConstantValue.SYMBOL_UNEQUAL)
		{
			interval = getUnequalInterval();
		}
		
		return interval;
	}
	
	/**
	 * 为>和>=号计算可用区间
	 * @return 一个区间
	 */
	private Interval getGreaterInterval()
	{
		Interval interval = new Interval();
		double x1 = c1.getX();
		double y1 = c1.getY();
		double x2 = c2.getX();
		double y2 = c2.getY();
		
		//if: 斜率为0
		if (Math.abs(y1 - y2) <= Double.MIN_VALUE)
		{
			if (y1 >= 0 || y2 >= 0)
			{
				interval.setLeftBoundary(x1);
				interval.setRightBoundary(x2);
			}
			else if (y1 <= 0 || y2 <= 0)
			{
				interval = null;
			}
		}
		else	//斜率不为0
		{
			if (y1 >= 0)
			{
				if (y2 >= 0)
				{
					interval.setLeftBoundary(x1);
					interval.setRightBoundary(x2);
				}
				else
				{
					//计算零点
					double zeroCoodinate = (x1*y2-x2*y1)/(y2-y1);
					interval.setLeftBoundary(x1);
					interval.setRightBoundary(zeroCoodinate);
				}
			}
			else
			{
				if (y2 <= 0)
				{
					interval = null;
				}
				else
				{
					//计算零点
					double zeroCoodinate = (x1*y2-x2*y1)/(y2-y1);
					interval.setLeftBoundary(zeroCoodinate);
					interval.setRightBoundary(x2);
				}
			}
		}
		return interval;
	}
	
	/**
	 * 为<和<=计算可用区间
	 * @return 一个区间
	 */
	private Interval getLessInteval()
	{
		Interval interval = new Interval();
		double x1 = c1.getX();
		double y1 = c1.getY();
		double x2 = c2.getX();
		double y2 = c2.getY();
		
		if (Math.abs(y1 - y2) <= Double.MIN_VALUE)
		{
			if (y1 >= 0 || y2 >= 0)
			{
				interval = null;
			}
			else if (y1 <= 0 || y2 <= 0)
			{
				interval.setLeftBoundary(x1);
				interval.setRightBoundary(x2);
			}
		}
		else
		{
			if (y1 <= 0)
			{
				if (y2 <= 0)
				{
					interval.setLeftBoundary(x1);
					interval.setRightBoundary(x2);
				}
				else
				{
					//计算零点
					double zeroCoodinate = (x1*y2-x2*y1)/(y2-y1);
					interval.setLeftBoundary(x1);
					interval.setRightBoundary(zeroCoodinate);
				}
			}
			else
			{
				if (y2 >= 0)
				{
					interval = null;
				}
				else
				{
					//计算零点
					double zeroCoodinate = (x1*y2-x2*y1)/(y2-y1);
					interval.setLeftBoundary(zeroCoodinate);
					interval.setRightBoundary(x2);
				}
			}
		}
		return interval;
	}
	
	/**
	 * 为==计算可用区间
	 * @return 一个区间
	 */
	private Interval getEqualInterval()
	{
		Interval interval = new Interval();
		interval.setLeftBoundary(c1.getX());
		interval.setRightBoundary(c2.getX());
		return interval;
	}
	
	/**
	 * 为!=计算可用区间
	 * @return 一个区间
	 */
	private Interval getUnequalInterval()
	{
		Interval interval = new Interval();
		interval.setLeftBoundary(c1.getX());
		interval.setRightBoundary(c2.getX());
		return interval;
	}

	public Coodinate getC1() {
		return c1;
	}

	public void setC1(Coodinate c1) {
		this.c1 = c1;
	}

	public Coodinate getC2() {
		return c2;
	}

	public void setC2(Coodinate c2) {
		this.c2 = c2;
	}

	public int getComparisonOperator() {
		return comparisonOperator;
	}

	public void setComparisonOperator(int comparisonOperator) {
		this.comparisonOperator = comparisonOperator;
	}
	
}
